package application

import "context"

const V2rayBoundProtocolDokodemoDoor = "dokodemo-door" // 任意门
const V2rayBoundProtocolHttp = "http"                  // HTTP
const V2rayBoundProtocolMTProto = "mtproto"            // Telegram专用协议
const V2rayBoundProtocolShadowSocks = "shadowsocks"    // ShadowSocks协议
const V2rayBoundProtocolSocks = "socks"                // Socks协议
const V2rayBoundProtocolVMess = "vmess"                // VMess协议
const V2rayBoundProtocolBlackhole = "blackhole"        // 黑洞
const V2rayBoundProtocolDns = "dns"                    // DNS协议
const V2rayBoundProtocolFreedom = "freedom"            // freedom

type V2rayNetwork string

const (
	V2rayNetworkNone   = V2rayNetwork("")
	V2rayNetworkTcp    = V2rayNetwork("tcp")
	V2rayNetworkUdp    = V2rayNetwork("udp")
	V2rayNetworkTcpUdp = V2rayNetwork("tcp,udp")
)

type V2rayStreamSettingsNetwork string

const (
	V2rayStreamSettingsNetworkTcp          = V2rayStreamSettingsNetwork("tcp")
	V2rayStreamSettingsNetworkKcp          = V2rayStreamSettingsNetwork("kcp")
	V2rayStreamSettingsNetworkWebsocket    = V2rayStreamSettingsNetwork("ws")
	V2rayStreamSettingsNetworkHttp2        = V2rayStreamSettingsNetwork("http")
	V2rayStreamSettingsNetworkDomainSocket = V2rayStreamSettingsNetwork("domainsocket")
	V2rayStreamSettingsNetworkQuic         = V2rayStreamSettingsNetwork("quic")
)

type V2rayFreedomDomainStrategy string

const (
	V2rayFreedomDomainStrategyAsIs    = V2rayFreedomDomainStrategy("AsIs")
	V2rayFreedomDomainStrategyUseIp   = V2rayFreedomDomainStrategy("UseIP")
	V2rayFreedomDomainStrategyUseIpV4 = V2rayFreedomDomainStrategy("UseIPv4")
	V2rayFreedomDomainStrategyUseIpV6 = V2rayFreedomDomainStrategy("UseIPv6")
)

// V2ray V2ray应用接口定义
type V2ray interface {
	Application

	// GetConfig 获取配置对象
	GetConfig() *V2rayConfig

	// SetInbound 设置入站协议
	SetInbound(ctx context.Context, id string, bound *V2rayBound) error

	// RemoveInbound 移除入站协议
	RemoveInbound(ctx context.Context, id string) error

	// SetOutbound 设置出站协议
	SetOutbound(ctx context.Context, id string, bound *V2rayBound) error

	// RemoveOutbound 移除出站协议
	RemoveOutbound(ctx context.Context, id string) error
}

type V2rayConfig struct {
	Inbounds  map[string]*V2rayBound `json:"inbounds"`  // 入站协议配置，有效的入站协议有: dokodemo-door/http/mtproto/shadowsocks/socks/vmess
	Outbounds map[string]*V2rayBound `json:"outbounds"` // 出站协议配置，有效的出站协议有: blackhole/dns/freedom/http/mtproto/shadowsocks/socks/vmess
	Router    struct{}               `json:"-"`         // TODO
	Log       struct{}               `json:"-"`         // TODO
	Stats     struct{}               `json:"-"`         // TODO
	Transport struct{}               `json:"-"`         // TODO
	Policy    struct{}               `json:"-"`         // TODO
}

type V2rayBound struct {
	Id       string `json:"id"`       // 配置对象ID
	Tag      string `json:"tag"`      // 自定义标识，不为空时唯一
	Protocol string `json:"protocol"` // 协议类型，指定哪一种协议配置有效
	Inbound  struct {
		Listen string `json:"listen"` // 监听地址
		Port   int    `json:"port"`   // 监听端口
	} `json:"inbound"` // 入站协议的私有配置，入站协议有效
	Outbound struct {
		SendThrough string `json:"send_through"` // 用于发送数据的IP地址，默认为0.0.0.0
	} `json:"outbound"` // 出站协议的私有配置，出站协议有效
	StreamSettings V2rayStreamSettings `json:"stream_settings"` // 传输方式配置
	ProxySettings  struct {
		Enable bool   `json:"enable"` // 是否启用此项配置
		Tag    string `json:"tag"`    // 出站配置的唯一标识
	} `json:"proxy_settings"` // 指定是否将数据转发向另一个出站代理
	Blackhole struct {
		Response struct {
			Type string `json:"type"` // 类型，默认为none，可选http
		} `json:"response"` // 响应配置
	} `json:"blackhole"` // 黑洞，仅用于出站
	DNS struct {
		Network string `json:"network"` // DNS链接方式，可选tcp和udp，允许不指定
		Address string `json:"address"` // DNS服务器地址，允许不指定
		Port    int    `json:"port"`    // DNS服务器端口，允许不指定
	} `json:"dns"` // DNS协议，仅用于出站
	Dokodemo struct {
		Address        string       `json:"address"`         // 转发的目标地址
		Port           int          `json:"port"`            // 转发的目标端口
		Network        V2rayNetwork `json:"network"`         // 转发的协议类型，可选：tcp/udp/tcp,udp
		Timeout        int64        `json:"timeout"`         // 超时时间，单位秒
		FollowRedirect bool         `json:"follow_redirect"` // 跟踪转发，开启此选项允许address为空
		UserLevel      int          `json:"user_level"`      // 用户等级
	} `json:"dokodemo"` // 任意门，仅用于入站
	Freedom struct {
		DomainStrategy V2rayFreedomDomainStrategy `json:"domain_strategy"` // 解析模式，默认AsIs，可选: AsIs|UseIP|UseIPv4|UseIPV6
		Redirect       string                     `json:"redirect"`        // 强制转发的目标地址，可以为空
		UserLevel      int                        `json:"user_level"`      // 用户等级
	} `json:"freedom"` // Freedom出站协议
	Http struct {
		Inbound struct {
			Timeout          int64               `json:"timeout"`           // 超时时间，单位秒
			AllowTransparent bool                `json:"allow_transparent"` // 是否允许转发全部HTTP请求
			Accounts         []*V2rayBaseAccount `json:"accounts"`          // 账号列表
			UserLevel        int                 `json:"user_level"`        // 用户等级
		} `json:"inbound"`
		Outbound struct {
			Servers []*V2rayHttpServer `json:"servers"` // 服务器列表
		} `json:"outbound"`
	} `json:"http"` // HTTP协议
	MTProto struct {
		User struct {
			Email  string `json:"email"`  // 邮件地址
			Secret string `json:"secret"` // 验证秘钥，必须为32位长度的字符串
			Level  int    `json:"level"`  // 等级
		} `json:"user"` // 用户身份配置
	} `json:"mt_proto"` // Telegram专用的代理协议
	ShadowSocks struct {
		Inbound struct {
			Email    string       `json:"email"`    // 邮件地址，可为空
			Method   string       `json:"method"`   // 加密方式，此项不能为空，可选:aes-256-cfb/aes-128-cfb/chacha20/chacha20-ietf/aes-256-gcm/aes-128-gcm/chacha20-poly1305
			Password string       `json:"password"` // 验证密码，此项不能为空
			OTA      bool         `json:"ota"`      // 是否强制开启OTA，默认为false
			Network  V2rayNetwork `json:"network"`  // 接受的连接类型，可选: tcp/udp/tcp,udp
		} `json:"inbound"` // 入站配置
		Outbound struct {
			Servers []*V2rayShadowSocksServer `json:"servers"` // 服务器列表
		} `json:"outbound"` // 出站配置
	} `json:"shadow_socks"` // SS协议，区分入站与出站配置
	Socks struct {
		Inbound struct {
			Auth      string              `json:"auth"`       // 验证类型，默认为noauth，可选: noauth/password
			Accounts  []*V2rayBaseAccount `json:"accounts"`   // 账号列表
			UDP       bool                `json:"udp"`        // 是否支持UDP协议
			Ip        string              `json:"ip"`         // 开启UDP时需要给出监听的IP地址，默认为127.0.0.1
			UserLevel int                 `json:"user_level"` // 用户等级
		} `json:"inbound"` // 入站配置
		Outbound struct {
			Servers []*V2raySocksServer `json:"servers"` // 服务器列表
		} `json:"outbound"` // 出站配置
	} `json:"socks"` // SOCKS协议，区分入站与出站配置
	VMess struct {
		Inbound struct {
			Clients                   []*V2rayVMessClient `json:"clients"`                     // 用户列表
			DisableInsecureEncryption bool                `json:"disable_insecure_encryption"` // 是否禁用不安全的加密协议，默认为false
		} `json:"inbound"` // 入站配置
		Outbound struct {
			Vnext []*V2rayVMessVnext `json:"vnext"` // 服务器配置
		} `json:"outbound"` // 出站配置
	} `json:"vmess"` // VMess协议，区分入站与出站配置
}

type V2rayStreamSettings struct {
	Enable      bool                       `json:"enable"`  // 是否启用传入配置
	Network     V2rayStreamSettingsNetwork `json:"network"` // 传输类型
	TlsSettings struct {
		ClientOnly bool   `json:"client_only"` // 是否仅客户端有效，设置此选项时服务端不启用TLS配置，但是客户端的VMess配置链接将会设置TLS安全选项
		Security   string `json:"security"`    // 安全类型，none或tls，默认为none
		ServerName string `json:"server_name"` // TLS域名
	} `json:"tls_settings"`
	TcpSettings struct {
		Header struct {
			Type string `json:"type"` // 默认为none
		} `json:"header"`
	} `json:"tcp_settings"`
	KcpSettings struct {
		Mtu              int  `json:"mtu"`               // 传输单元配置，允许的范围为576-1460，默认为1350
		Tti              int  `json:"tti"`               // 传输频率，允许的范围为1-100，默认为50
		UplinkCapacity   *int `json:"uplink_capacity"`   // 上行带宽限制，单位MB，默认值为5，允许设置为0
		DownlinkCapacity *int `json:"downlink_capacity"` // 下行带宽限制，单位MB，默认值为20，允许设置为0
		Congestion       bool `json:"congestion"`        // 是否启用拥塞控制
		ReadBufferSize   int  `json:"read_buffer_size"`  // 单个连接的读缓冲区大小，单位MB，默认为2
		WriteBufferSize  int  `json:"write_buffer_size"` // 单个连接的写缓冲区大小，单位MB，默认为2
		Header           struct {
			Type string `json:"type"` // 伪装类型，默认为none，可选: none/srtp/utp/wechat-video/dtls/wireguard
		} `json:"header"` // 头信息配置
	} `json:"kcp_settings"`
	WebsocketSettings struct {
		Path    string            `json:"path"`    // 默认值为/
		Headers map[string]string `json:"headers"` // 头信息，KEY/VALUE对
	} `json:"websocket_settings"`
	DomainSocketSettings struct {
		Path string `json:"path"` // 一个文件路径，V2ray启动前，此文件必须不存在，但路径必须有效(文件夹有效)
	} `json:"domain_socket_settings"`
	Http2Settings struct {
		Host []string `json:"host"`
		Path string   `json:"path"` // 默认值为/
	} `json:"http2_settings"`
	QuicSettings struct {
		Security string `json:"security"` // 加密类型，默认为none，可选: none/aes-128-gcm/chacha20-poly1305
		Key      string `json:"key"`      // 加密类型不为none时用于加密数据
		Header   struct {
			Type string `json:"type"` // 伪装类型，默认为none，可选: none/srtp/utp/wechat-video/dtls/wireguard
		} `json:"header"` // 头信息配置
	} `json:"quic_settings"`
}

type V2rayBaseAccount struct {
	Username string `json:"username"` // 用户名
	Password string `json:"password"` // 密码
	Level    int    `json:"level"`    // 用户等级，默认为0，仅Socks协议的Outbound配置内有效
}

type V2rayHttpServer struct {
	Address string              `json:"address"` // 服务器地址，不能为空
	Port    int                 `json:"port"`    // 服务器端口，不能为空
	Users   []*V2rayBaseAccount `json:"users"`   // 用户列表，可以为空，为空时不进行身份验证
}

type V2rayShadowSocksServer struct {
	Email    string `json:"email"`    // 邮件地址，可为空
	Address  string `json:"address"`  // 服务器地址，不能为空
	Port     int    `json:"port"`     // 服务器端口，不能为空
	Method   string `json:"method"`   // 加密方式，此项不能为空，可选:aes-256-cfb/aes-128-cfb/chacha20/chacha20-ietf/aes-256-gcm/aes-128-gcm/chacha20-poly1305
	Password string `json:"password"` // 验证密码，此项不能为空
	OTA      bool   `json:"ota"`      // 是否强制开启OTA，默认为false
	Level    int    `json:"level"`    // 用户等级
}

type V2raySocksServer struct {
	Address string              `json:"address"` // 服务器地址，不能为空
	Port    int                 `json:"port"`    // 服务器端口，不能为空
	Users   []*V2rayBaseAccount `json:"users"`   // 用户列表，可以为空，为空时不进行身份验证
}

type V2rayVMessClient struct {
	Id       string `json:"id"`       // ID
	Level    int    `json:"level"`    // 用户等级，默认为0
	Email    string `json:"email"`    // 邮件地址，可为空
	Security string `json:"security"` // 加密方式，仅出站配置有效，默认auto，不支持更改
}

type V2rayVMessVnext struct {
	Address string              `json:"address"` // 服务器地址，不能为空
	Port    int                 `json:"port"`    // 服务器端口，不能为空
	Users   []*V2rayVMessClient `json:"users"`   // 用户列表，可以为空，为空时不进行身份验证
}
